﻿/*
 *	Copyright (c) 2009 Queensland University of Technology. All rights reserved.
 *	The QUT Bioinformatics Collection is open source software released under the 
 *	Microsoft Public License (Ms-PL): http://www.microsoft.com/opensource/licenses.mspx.
 */
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace QUT.Bio.SilverMap.ObjectModel {
	/// <summary>
	/// Represents a BLAST HSP between a query feature and a subject feature.
	/// <para>Two hits are considered to be equal if they connect the same pair of features, as determined by the unique feature ids.</para>
	/// </summary>

	public class Hit : IComparable<Hit>, IEquatable<Hit> {
		/// <summary>
		/// Used to signify the absence of sequence/alignment data.
		/// </summary>
		public static readonly string SEQUENCE_DATA_UNAVAILABLE = "Sequence data unavailable";

		private IFeature queryFeature;
		private IFeature hitFeature;
		private double eValue = Double.MaxValue;
		private long identities = 0;
		private long positives = 0;
		private string midline = SEQUENCE_DATA_UNAVAILABLE;

		public Hit (
			IFeature from,
			IFeature to
		) {
			this.queryFeature = from;
			this.hitFeature = to;
		}

		#region Property: QueryFeature
		/// <summary>
		/// Gets a reference to the subsequence of the query sequence that
		/// appears in this hit.
		/// </summary>

		public IFeature QueryFeature {
			get {
				return queryFeature;
			}
		}
		#endregion

		#region Property: HitFeature
		/// <summary>
		/// Gets a reference to the subsequence of the subject sequence that
		/// matches agains the query feature.
		/// </summary>

		public IFeature HitFeature {
			get {
				return hitFeature;
			}
		}
		#endregion

		#region Method: Equals
		public bool Equals ( Hit other ) {
			return this.CompareTo( other ) == 0;
		}

		public override bool Equals ( object obj ) {
			return obj is Hit ? Equals( (Hit) obj ) : false;
		}

		public override int GetHashCode () {
			return queryFeature.GetHashCode() << 5 + hitFeature.GetHashCode();
		}
		#endregion

		#region Method: CompareTo
		/// <summary>
		/// Compares this Hit to another, by queryFeature, hitFeature, and eValue.
		/// </summary>
		/// <param name="other"></param>
		/// <returns></returns>
		
		public int CompareTo ( Hit other ) {
			int result = queryFeature.CompareTo( other.queryFeature );
			
			if ( result == 0 ) {
				result = hitFeature.CompareTo( other.hitFeature );
			}
			
			if ( result == 0 ) {
				result = eValue.CompareTo( other.eValue );
			}
			
			return result;
		}
		#endregion

		#region Property: EValue
		/// <summary>
		/// Get or set the EValue
		/// </summary>

		public double EValue {
			get {
				return eValue;
			}
			set {
				eValue = value;
			}
		}
		#endregion

		#region Property: Identitites
		/// <summary>
		/// Get or set the indentity count
		/// </summary>

		public long Identities {
			get {
				return identities;
			}
			set {
				identities = value;
			}
		}
		#endregion

		#region Property: Positives
		/// <summary>
		/// Get or set the Positives count.
		/// </summary>

		public long Positives {
			get {
				return positives;
			}
			set {
				positives = value;
			}
		}
		#endregion

		#region Property: QueryFrom
		/// <summary>
		/// Get or set the query end position.
		/// </summary>

		public long QueryFrom {
			get {
				return queryFeature.Start;
			}
		}
		#endregion

		#region Property: QueryTo
		/// <summary>
		/// Get or set the query end position.
		/// </summary>

		public long QueryTo {
			get {
				return queryFeature.End;
			}
		}
		#endregion

		#region Property: HitFrom
		/// <summary>
		/// Get or set the hit start position.
		/// </summary>

		public long HitFrom {
			get {
				return hitFeature.Start;
			}
		} 
		#endregion

		#region Property: HitTo
		/// <summary>
		/// Get or set the hit end position.
		/// </summary>

		public long HitTo {
			get {
				return hitFeature.End;
			}
		} 
		#endregion

		#region Property: QuerySequence
		/// <summary>
		/// Get or set the query sequence 
		/// </summary>

		public string QuerySequence {
			get {
				return queryFeature.SequenceData;
			}
		} 
		#endregion

		#region Property: Midline
		/// <summary>
		/// Get or set the Midline.
		/// </summary>

		public string Midline {
			get {
				return midline;
			}
			set {
				midline = value;
			}
		} 
		#endregion

		#region Property: HitSequence
		/// <summary>
		/// Get or set the hit sequence.
		/// </summary>

		public string HitSequence {
			get {
				return hitFeature.SequenceData;
			}
		}
		#endregion
	}
}
